package static_parking

import (
	"bytes"
	"crypto/md5"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"parking-lot-go-push/model"
	model_config "parking-lot-go-push/model/config"

	"sort"
	"strings"

	"parking-lot-go-push/logger"
)

type ResponseData struct {
	Code int                      `json:"code"`
	Msg  string                   `json:"msg"`
	Data []map[string]interface{} `json:"data"`
}

type StaicSigner struct {
	AccessKey      string
	AccessPassword string
	MuchId         string
}

func NewSigner() *StaicSigner {

	var configStaticParkingData model_config.ConfigStaticParkingStruct
	model.GetModelDataFirst(
		model.Db,
		configStaticParkingData.TableName(),
		&configStaticParkingData,
		model.QueryOptions{
			Conditions: map[string]interface{}{
				"status": 1,
			},
		})

	return &StaicSigner{
		AccessKey:      configStaticParkingData.AccessKey,
		AccessPassword: configStaticParkingData.AccessPassword,
		MuchId:         configStaticParkingData.MuchId,
	}
}

var staticPushLogger = logger.NewLogger("static", "push")

// 签名计算
func (s *StaicSigner) Sign(data map[string]interface{}) string {

	//数组key抽出排序
	keys := make([]string, 0, len(data))
	for k := range data {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	//根据key 排序value
	values := make([]string, len(keys))
	for i, k := range keys {
		switch v := data[k].(type) {
		case string:
			values[i] = v
		case int, int64, float64: // 添加其他可能的数值类型
			values[i] = fmt.Sprintf("%v", v)
		// 添加其他类型的处理...
		default:
			// 对于其他类型，你可以根据实际情况处理
			values[i] = fmt.Sprintf("%v", v)
		}
	}

	//值转换成字符串
	stringToHash := strings.Join(values, "")

	//字符串拼接
	hashInput := s.AccessKey + stringToHash + s.AccessPassword

	//md5加密
	hash := md5.Sum([]byte(hashInput))

	//字符串截取
	result := fmt.Sprintf("%x", hash)[8:24]

	return result
}

// curl get请求
func (s *StaicSigner) CurlPostJson(url, sign string, jsonData interface{}) (err error, returnData []map[string]interface{}) {

	var configStaticParkingData model_config.ConfigStaticParkingStruct
	model.GetModelDataFirst(
		model.Db,
		configStaticParkingData.TableName(),
		&configStaticParkingData,
		model.QueryOptions{
			Conditions: map[string]interface{}{
				"status": 1,
			},
		})

	//请求地址拼接
	url = configStaticParkingData.PushBaseUrl + url
	staticPushLogger.Info(fmt.Sprintf("推送接口:%s", url))

	// 将 JSON 数据封装为请求体
	jsonBytes, err := json.Marshal(jsonData)
	if err != nil {
		staticPushLogger.Error(fmt.Sprintf("转换json失败:%s", err.Error()))
		staticPushLogger.Error(jsonData)
		return errors.New("转换json失败"), returnData
	}

	// 创建自定义的 HTTP 客户端
	client := &http.Client{}

	// 创建 POST 请求
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBytes))
	if err != nil {
		staticPushLogger.Error(fmt.Sprintf("创建请求失败:%s", err.Error()))
		return errors.New("创建请求失败"), returnData
	}

	// 设置请求头
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("accessKey", s.AccessKey)
	req.Header.Set("sign", sign)
	req.Header.Set("muchId", s.MuchId)

	//日志记录
	staticPushLogger.Info(fmt.Sprintf("accessKey:%s,sign:%s,muchId:%s", s.AccessKey, sign, s.MuchId))
	staticPushLogger.Info(fmt.Sprintf("data:%s", bytes.NewBuffer(jsonBytes)))

	// 发起请求
	response, err := client.Do(req)
	if err != nil {
		staticPushLogger.Error(fmt.Sprintf("请求失败:%s", err.Error()))
		return errors.New("请求失败"), returnData
	}

	defer response.Body.Close()

	// 读取响应内容
	responseBody, err := io.ReadAll(response.Body)
	if err != nil {
		staticPushLogger.Error(fmt.Sprintf("获取响应内容失败:%s", err.Error()))
		return errors.New("获取响应内容失败"), returnData
	}

	var responseData ResponseData
	if err := json.Unmarshal(responseBody, &responseData); err != nil {
		staticPushLogger.Error(fmt.Sprintf("解析响应结果失败:%s", err.Error()))
		staticPushLogger.Error(responseBody)
		return errors.New("解析响应结果失败"), returnData
	}

	staticPushLogger.Info("---- 接收静态反馈 ----")
	staticPushLogger.Info("responseData:", responseData)

	if responseData.Code == 200 {
		return nil, responseData.Data
	}

	return errors.New(responseData.Msg), returnData
}
